//
//  AtomicProperty.swift
//  EasyCoding
//
//  Created by JY_NEW on 2020/6/4.
//

import Foundation

///多读单写
@propertyWrapper
public struct PWAtomic<Value> {
    let queue = DispatchQueue(label: "Atomic write access queue", attributes: .concurrent)
    var value: Value
    
    public init(wrappedValue: Value) {
        self.value = wrappedValue
    }
    
    public var wrappedValue: Value {
        get {
            return queue.sync { value }
        }
        set {
            queue.sync(flags: .barrier) { value = newValue }
        }
    }
    
    @discardableResult
    public mutating func mutate(_ mutation: (inout Value) throws -> Void) rethrows -> Value {
        return try queue.sync(flags: .barrier) {
            try mutation(&value)
            return value
        }
    }
}

extension PWAtomic where Value: Strideable, Value.Stride: ExpressibleByIntegerLiteral {
    /// 移动到下一个并获取旧值
    public mutating func move() -> Value {
        return queue.sync(flags: .barrier) {
            let v = value
            value = value.advanced(by: 1)
            return v
        }
    }
    /// 移动到下一个并获取结果
    public mutating func increase() -> Value {
        return queue.sync(flags: .barrier) {
            value = value.advanced(by: 1)
            return value
        }
    }
    /// 移动到还一个并获取结果
    public mutating func decrease() -> Value {
        return queue.sync(flags: .barrier) {
            value = value.advanced(by: -1)
            return value
        }
    }
}
